package com.virjar.hermes.hermesadmin.controller;

import com.google.common.base.Function;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.virjar.hermes.hermesadmin.dao.DeviceAppMapper;
import com.virjar.hermes.hermesadmin.dao.DeviceMapper;
import com.virjar.hermes.hermesadmin.dao.TargetAppMapper;
import com.virjar.hermes.hermesadmin.model.CommonRes;
import com.virjar.hermes.hermesadmin.model.Device;
import com.virjar.hermes.hermesadmin.model.DeviceApp;
import com.virjar.hermes.hermesadmin.model.TargetApp;
import com.virjar.hermes.hermesadmin.servicemanager.AppServiceRegistry;
import com.virjar.hermes.hermesadmin.util.Constant;
import com.virjar.hermes.hermesadmin.util.ReturnUtil;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;

/**
 * Created by virjar on 2018/9/6.<br>
 * 服务维度管理,每个app在每个设备上面计算为一个服务
 */
@Slf4j
@RestController
@RequestMapping("/service")
public class DeviceServiceController {

    @Resource
    private DeviceAppMapper deviceAppMapper;

    @Resource
    private TargetAppMapper targetAppMapper;

    @Resource
    private DeviceMapper deviceMapper;

    @Resource
    private AppServiceRegistry appServiceRegistry;

    /**
     *
     */
    @ApiOperation(value = "查看服务列表列表", notes = "可以查看某个设备上面的服务,或者查看某个服务在那些设备上")
    @GetMapping(value = "/list")
    @ResponseBody
    public CommonRes<List<DeviceApp>> list(@RequestParam(value = "servicePackage", required = false) String servicePackage,
                                           @RequestParam(value = "deviceMac", required = false) String deviceMac) {
        if (StringUtils.isBlank(servicePackage)
                && StringUtils.isBlank(deviceMac)) {
            return ReturnUtil.failed("servicePackage 和 deviceMac 不能同时为空");
        }
        return ReturnUtil.success(deviceAppMapper.selectByMacOrService(deviceMac, servicePackage));
    }

    /**
     *
     */
    @ApiOperation(value = "onlineDevice", notes = "查看在线的服务")
    @GetMapping(value = "/onlineDevice")
    @ResponseBody
    public CommonRes<List<String>> onlineService() {
        return ReturnUtil.success(appServiceRegistry.serviceList());
    }


    @ApiOperation(value = "通知所有设备,安装某个指定服务", notes = "该请求只是一个通知,需要客户端和service交互,获取到最新配置,然后下载对应apk,挂载服务,整个时长可能有几分钟,所以安装到服务可用可能存在较大时差")
    @GetMapping(value = "/deployAllDevice")
    @ResponseBody
    public CommonRes<Integer> deployAllDevice(@RequestParam("servicePackage") String servicePackage) {
        TargetApp targetApp = targetAppMapper.findAvilable(servicePackage);
        if (targetApp == null) {
            return ReturnUtil.failed("服务:" + servicePackage + " 不存在,请先上线该服务");
        }

        int totalInstalled = 0;
        while (true) {
            //这里一个批次1024个,分批次处理
            List<Device> unInstalledDevice = deviceMapper.findUnInstalledDevice(servicePackage);
            if (unInstalledDevice.size() == 0) {
                break;
            }
            for (Device device : unInstalledDevice) {
                DeviceApp deviceApp = new DeviceApp();
                deviceApp.setAppPackage(servicePackage);
                deviceApp.setDeviceMac(device.getMac());
                deviceApp.setDeviceId(device.getId());
                deviceApp.setStatus(Constant.serviceStatusInstalling);
                deviceAppMapper.insert(deviceApp);
                totalInstalled++;
            }
        }
        return ReturnUtil.success(totalInstalled);
    }

    private Splitter deviceMacSplitter = Splitter.on('_').omitEmptyStrings().trimResults();

    @ApiOperation(value = "通知某些设备,安装某个指定服务", notes = "该请求只是一个通知,需要客户端和service交互,获取到最新配置,然后下载对应apk,挂载服务,整个时长可能有几分钟,所以安装到服务可用可能存在较大时差")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "targetDeviceMac", value = "设备硬件标记,可以传递多个,多个使用下划线分割(_)", dataType = "java.lang.String", paramType = "query")
    })
    @GetMapping(value = "/deploySomeDevices")
    @ResponseBody
    public CommonRes<Integer> deploySomeDevices(@RequestParam("servicePackage") String servicePackage
            , @RequestParam("targetDeviceMac") String targetDeviceMac) {
        Set<String> installedMac = Sets.newHashSet(Lists.transform(deviceAppMapper.selectByMacOrService(null, servicePackage), new Function<DeviceApp, String>() {
            @Override
            public String apply(DeviceApp input) {
                return input.getDeviceMac();
            }
        }));
        int totalInstalled = 0;
        for (String mac : deviceMacSplitter.split(targetDeviceMac)) {
            Device device = deviceMapper.selectByMac(mac);
            if (device == null) {
                log.warn("can not find device:{}", mac);
                continue;
            }
            if (installedMac.contains(mac)) {
                continue;
            }
            DeviceApp deviceApp = new DeviceApp();
            deviceApp.setAppPackage(servicePackage);
            deviceApp.setDeviceMac(device.getMac());
            deviceApp.setDeviceId(device.getId());
            deviceApp.setStatus(Constant.serviceStatusInstalling);
            deviceAppMapper.insert(deviceApp);
            totalInstalled++;
        }
        return ReturnUtil.success(totalInstalled);
    }
}
